from django.contrib.sessions.models import Session
from django.db.models.signals import post_save, m2m_changed
from django.dispatch import receiver

from apps.base.models import Log
from service.middleware import get_request  # 导入获取 request 的方法


@receiver(post_save)
def log_create_or_update(sender, instance, created, **kwargs):
    """
    :param sender: 若是 post_save 信号,那么 sender 会是那个被保存的模型类,通常是模型本身
    :param instance: 这个参数是你在数据库中进行操作的那条记录.
    :param created: created 为 True 时,表示是创建（save）了一个新对象; created 为 False 时, 表示对象是已经存在的(即进行了更新操作).
    :return:
    """
    request = get_request()  # 获取当前线程的 request 对象
    if sender == Log or sender == Session or not request:
        # 避免循环记录日志 Log新增日志时别调用该信号 ; 在登陆成功后,会往session表里写数据,也会触发post_save信号,但不需要记录日志.
        # 用脚本批量添加数据时也会触发post_save信号 > request值为None.. 也不必记录这个批量脚本的日志
        return

    user = request.user.nickname
    # 因为删除使用的是逻辑删除,删除只是改变了依旧是save.. 所以执行删除时的action通过访问的url进行判断.
    url = request.path_info
    if url and "del" in url:
        action = "delete"
    else:
        action = 'create' if created else 'update'
    model_name = sender.__name__
    object_id = instance.id
    object_repr = str(instance)  # 使用对象的 `__str__` 方法来表示对象
    browser = request.META.get('HTTP_USER_AGENT', '')

    # 获取请求的 IP 地址和 URL
    ip_address = request.META.get('REMOTE_ADDR')
    # 创建日志记录
    Log.objects.create(
        user=user,
        action=action,
        model_name=model_name,
        object_id=object_id,
        object_repr=object_repr,
        url=url,
        browser=browser,
        status=200,
        ip_address=ip_address,
        message=f"用户{user}对{model_name}表中id为{object_id}的记录进行了{action}的操作!"
    )


@receiver(m2m_changed)
def log_m2m_change(sender, action, instance, pk_set, **kwargs):
    """监听 ManyToManyField 的变化"""
    # print(sender, action, instance, pk_set, kwargs)
    if action == 'post_add':
        request = get_request()
        if sender == Log or sender == Session or not request:
            return

        user = request.user.nickname
        # 因为删除使用的是逻辑删除,删除只是改变了依旧是save.. 所以执行删除时的action通过访问的url进行判断.
        url = request.path_info
        action = "m2m_change"
        model_name = sender.__name__
        object_id = instance.id
        object_repr = str(instance)
        browser = request.META.get('HTTP_USER_AGENT', '')
        ip_address = request.META.get('REMOTE_ADDR')
        # 创建日志记录
        Log.objects.create(
            user=user,
            action=action,
            model_name=model_name,
            object_id=object_id,
            object_repr=object_repr,
            url=url,
            browser=browser,
            status=200,
            message=f"用户{user}对第三张表{model_name}进行了操作,{instance}对象对应{list(pk_set)}!",
            ip_address=ip_address
        )
